<script setup lang="ts">
import { computed, reactive, ref, watch } from 'vue';
import { NButton, NUpload, type UploadFileInfo, useMessage } from 'naive-ui';
import { addMappingRule, updateMappingRule, fetchMappingRuleDetail, detectFileFields, fetchTableFields } from '@/service/api';
import { $t } from '@/locales';

defineOptions({
  name: 'MappingRuleOperateDrawer'
});

interface Props {
  operateType: NaiveUI.TableOperateType;
  rowData?: Api.DataPlatform.MappingRule | null;
}

const props = defineProps<Props>();

interface Emits {
  (e: 'submitted'): void;
}

const emit = defineEmits<Emits>();

const message = useMessage();
const visible = defineModel<boolean>('visible', {
  default: false
});

const title = computed(() => {
  const titles: Record<NaiveUI.TableOperateType, string> = {
    add: '新增映射规则',
    edit: '编辑映射规则'
  };
  return titles[props.operateType];
});

type Model = Api.DataPlatform.MappingRuleEdit;

const model: Model = reactive(createDefaultModel());

function createDefaultModel(): Model {
  return {
    ruleName: '',
    ruleCode: '',
    fileType: 'CSV',
    parserConfig: '',
    fieldMappings: [],
    validationRules: [],
    remark: ''
  };
}

type RuleKey = Extract<keyof Model, 'ruleName' | 'ruleCode' | 'fileType' | 'fieldMappings'>;

const rules: Record<RuleKey, App.Global.FormRule> = {
  ruleName: {
    required: true,
    message: '请输入规则名称'
  },
  ruleCode: {
    required: true,
    message: '请输入规则编码'
  },
  fileType: {
    required: true,
    message: '请选择文件类型'
  },
  fieldMappings: {
    required: true,
    type: 'array',
    message: '请配置字段映射'
  }
};

const fileTypeOptions = [
  { label: 'CSV', value: 'CSV' },
  { label: 'XLS', value: 'XLS' },
  { label: 'XLSX', value: 'XLSX' },
  { label: 'XML', value: 'XML' },
  { label: 'JSON', value: 'JSON' },
  { label: 'SQL', value: 'SQL' }
];

// 文件上传
const uploadFileList = ref<UploadFileInfo[]>([]);
const detectingFields = ref(false);

async function handleFileUpload(options: { file: UploadFileInfo }) {
  if (!model.fileType) {
    message.error('请先选择文件类型');
    return;
  }

  detectingFields.value = true;
  try {
    const { data } = await detectFileFields(options.file.file as File, model.fileType);
    if (data) {
      sourceFields.value = data;
      message.success('字段检测成功');
    }
  } catch (error) {
    message.error('字段检测失败');
  } finally {
    detectingFields.value = false;
  }
}

// 源字段和目标字段
const sourceFields = ref<Api.DataPlatform.FieldInfo[]>([]);
const targetFields = ref<Api.DataPlatform.FieldInfo[]>([]);
const targetDatabase = ref('');
const targetTable = ref('');
const loadingTargetFields = ref(false);

async function handleLoadTargetFields() {
  if (!targetDatabase.value || !targetTable.value) {
    message.error('请输入数据库名和表名');
    return;
  }

  loadingTargetFields.value = true;
  try {
    const { data } = await fetchTableFields(targetDatabase.value, targetTable.value);
    if (data) {
      targetFields.value = data;
      message.success('目标字段加载成功');
    }
  } catch (error) {
    message.error('目标字段加载失败');
  } finally {
    loadingTargetFields.value = false;
  }
}

// 字段映射配置
function handleAddMapping() {
  model.fieldMappings.push({
    sourceField: '',
    targetField: '',
    sourceType: '',
    targetType: '',
    transformFunction: '',
    transformParams: '',
    defaultValue: '',
    nullable: true,
    description: ''
  });
}

function handleRemoveMapping(index: number) {
  model.fieldMappings.splice(index, 1);
}

// 转换函数选项
const transformFunctionOptions = [
  { label: '无', value: '' },
  { label: '转大写', value: 'UPPER' },
  { label: '转小写', value: 'LOWER' },
  { label: '日期格式化', value: 'DATE_FORMAT' },
  { label: '字符串截取', value: 'SUBSTRING' },
  { label: '正则替换', value: 'REGEX_REPLACE' }
];

// 校验规则配置
function handleAddValidation() {
  if (!model.validationRules) {
    model.validationRules = [];
  }
  model.validationRules.push({
    fieldName: '',
    validationType: 'NOT_NULL',
    validationParams: '',
    errorStrategy: 'MARK_ERROR',
    errorMessage: ''
  });
}

function handleRemoveValidation(index: number) {
  model.validationRules?.splice(index, 1);
}

const validationTypeOptions = [
  { label: '非空校验', value: 'NOT_NULL' },
  { label: '格式校验', value: 'FORMAT' },
  { label: '范围校验', value: 'RANGE' },
  { label: '枚举校验', value: 'ENUM' },
  { label: '唯一性校验', value: 'UNIQUE' }
];

const errorStrategyOptions = [
  { label: '跳过记录', value: 'SKIP_RECORD' },
  { label: '标记错误', value: 'MARK_ERROR' },
  { label: '终止任务', value: 'STOP_TASK' }
];

async function handleInitModel() {
  Object.assign(model, createDefaultModel());

  if (props.operateType === 'edit' && props.rowData) {
    const { data } = await fetchMappingRuleDetail(props.rowData.id);
    if (data) {
      Object.assign(model, data);
    }
  }
}

function closeDrawer() {
  visible.value = false;
}

const submitLoading = ref(false);

async function handleSubmit() {
  submitLoading.value = true;
  try {
    if (props.operateType === 'add') {
      await addMappingRule(model);
      message.success('新增成功');
    } else {
      await updateMappingRule(model);
      message.success('更新成功');
    }
    closeDrawer();
    emit('submitted');
  } catch (error) {
    // Error handled by request interceptor
  } finally {
    submitLoading.value = false;
  }
}

watch(visible, () => {
  if (visible.value) {
    handleInitModel();
    uploadFileList.value = [];
    sourceFields.value = [];
    targetFields.value = [];
  }
});
</script>

<template>
  <NDrawer v-model:show="visible" display-directive="show" :width="1000">
    <NDrawerContent :title="title" :native-scrollbar="false" closable>
      <NForm :model="model" :rules="rules" label-placement="left" :label-width="120">
        <NDivider title-placement="left">基本信息</NDivider>
        <NFormItem label="规则名称" path="ruleName">
          <NInput v-model:value="model.ruleName" placeholder="请输入规则名称" />
        </NFormItem>
        <NFormItem label="规则编码" path="ruleCode">
          <NInput v-model:value="model.ruleCode" placeholder="请输入规则编码" />
        </NFormItem>
        <NFormItem label="文件类型" path="fileType">
          <NSelect v-model:value="model.fileType" :options="fileTypeOptions" placeholder="请选择文件类型" />
        </NFormItem>
        <NFormItem label="备注" path="remark">
          <NInput v-model:value="model.remark" type="textarea" placeholder="请输入备注" />
        </NFormItem>

        <NDivider title-placement="left">字段检测</NDivider>
        <NFormItem label="上传文件">
          <NUpload
            v-model:file-list="uploadFileList"
            :max="1"
            :custom-request="handleFileUpload"
            :disabled="!model.fileType"
          >
            <NButton :loading="detectingFields">
              <icon-ic-round-upload class="mr-4px text-16px" />
              上传文件检测字段
            </NButton>
          </NUpload>
        </NFormItem>

        <NDivider title-placement="left">目标表配置</NDivider>
        <NSpace>
          <NFormItem label="数据库名">
            <NInput v-model:value="targetDatabase" placeholder="请输入数据库名" class="w-200px" />
          </NFormItem>
          <NFormItem label="表名">
            <NInput v-model:value="targetTable" placeholder="请输入表名" class="w-200px" />
          </NFormItem>
          <NButton type="primary" :loading="loadingTargetFields" @click="handleLoadTargetFields">
            加载目标字段
          </NButton>
        </NSpace>

        <NDivider title-placement="left">
          字段映射配置
          <NButton size="small" type="primary" class="ml-12px" @click="handleAddMapping">
            <icon-ic-round-plus class="mr-4px text-16px" />
            添加映射
          </NButton>
        </NDivider>
        <NFormItem path="fieldMappings">
          <div class="w-full">
            <NSpace v-for="(mapping, index) in model.fieldMappings" :key="index" vertical class="w-full mb-12px">
              <NCard size="small" :bordered="true">
                <template #header>
                  <NSpace justify="space-between">
                    <span>映射 {{ index + 1 }}</span>
                    <NButton size="small" type="error" @click="handleRemoveMapping(index)">
                      <icon-ic-round-delete class="text-16px" />
                    </NButton>
                  </NSpace>
                </template>
                <NGrid :cols="2" :x-gap="12" :y-gap="12">
                  <NGridItem>
                    <NFormItem label="源字段">
                      <NSelect
                        v-model:value="mapping.sourceField"
                        :options="sourceFields.map(f => ({ label: f.fieldName, value: f.fieldName }))"
                        placeholder="请选择源字段"
                      />
                    </NFormItem>
                  </NGridItem>
                  <NGridItem>
                    <NFormItem label="目标字段">
                      <NSelect
                        v-model:value="mapping.targetField"
                        :options="targetFields.map(f => ({ label: f.fieldName, value: f.fieldName }))"
                        placeholder="请选择目标字段"
                      />
                    </NFormItem>
                  </NGridItem>
                  <NGridItem>
                    <NFormItem label="转换函数">
                      <NSelect
                        v-model:value="mapping.transformFunction"
                        :options="transformFunctionOptions"
                        placeholder="请选择转换函数"
                      />
                    </NFormItem>
                  </NGridItem>
                  <NGridItem>
                    <NFormItem label="默认值">
                      <NInput v-model:value="mapping.defaultValue" placeholder="请输入默认值" />
                    </NFormItem>
                  </NGridItem>
                </NGrid>
              </NCard>
            </NSpace>
          </div>
        </NFormItem>

        <NDivider title-placement="left">
          校验规则配置
          <NButton size="small" type="primary" class="ml-12px" @click="handleAddValidation">
            <icon-ic-round-plus class="mr-4px text-16px" />
            添加校验
          </NButton>
        </NDivider>
        <NSpace v-for="(rule, index) in model.validationRules" :key="index" vertical class="w-full mb-12px">
          <NCard size="small" :bordered="true">
            <template #header>
              <NSpace justify="space-between">
                <span>校验规则 {{ index + 1 }}</span>
                <NButton size="small" type="error" @click="handleRemoveValidation(index)">
                  <icon-ic-round-delete class="text-16px" />
                </NButton>
              </NSpace>
            </template>
            <NGrid :cols="2" :x-gap="12" :y-gap="12">
              <NGridItem>
                <NFormItem label="字段名">
                  <NSelect
                    v-model:value="rule.fieldName"
                    :options="sourceFields.map(f => ({ label: f.fieldName, value: f.fieldName }))"
                    placeholder="请选择字段"
                  />
                </NFormItem>
              </NGridItem>
              <NGridItem>
                <NFormItem label="校验类型">
                  <NSelect v-model:value="rule.validationType" :options="validationTypeOptions" />
                </NFormItem>
              </NGridItem>
              <NGridItem :span="2">
                <NFormItem label="校验参数">
                  <!-- 非空校验 - 无需参数 -->
                  <div v-if="rule.validationType === 'NOT_NULL'" class="text-gray-500">
                    非空校验无需配置参数
                  </div>
                  
                  <!-- 格式校验 - 正则表达式 -->
                  <NSpace v-else-if="rule.validationType === 'FORMAT'" vertical class="w-full">
                    <NInput
                      v-model:value="rule.validationParams"
                      placeholder='请输入正则表达式，例如: {"pattern": "^\\d{11}$", "message": "手机号格式不正确"}'
                      type="textarea"
                      :rows="2"
                    />
                    <NText depth="3" class="text-12px">
                      示例: {"pattern": "^\\d{11}$", "message": "手机号格式不正确"}
                    </NText>
                  </NSpace>
                  
                  <!-- 范围校验 - 数值或日期范围 -->
                  <NSpace v-else-if="rule.validationType === 'RANGE'" vertical class="w-full">
                    <NInput
                      v-model:value="rule.validationParams"
                      placeholder='请输入范围配置，例如: {"type": "NUMBER", "min": "0", "max": "100"}'
                      type="textarea"
                      :rows="2"
                    />
                    <NText depth="3" class="text-12px">
                      数值示例: {"type": "NUMBER", "min": "0", "max": "100", "minInclusive": true, "maxInclusive": true}
                    </NText>
                    <NText depth="3" class="text-12px">
                      日期示例: {"type": "DATE", "min": "2024-01-01", "max": "2024-12-31"}
                    </NText>
                  </NSpace>
                  
                  <!-- 枚举校验 - 允许的值列表 -->
                  <NSpace v-else-if="rule.validationType === 'ENUM'" vertical class="w-full">
                    <NInput
                      v-model:value="rule.validationParams"
                      placeholder='请输入枚举值，例如: {"values": ["男", "女"], "caseSensitive": true}'
                      type="textarea"
                      :rows="2"
                    />
                    <NText depth="3" class="text-12px">
                      示例: {"values": ["男", "女", "未知"], "caseSensitive": true}
                    </NText>
                  </NSpace>
                  
                  <!-- 唯一性校验 -->
                  <NSpace v-else-if="rule.validationType === 'UNIQUE'" vertical class="w-full">
                    <NInput
                      v-model:value="rule.validationParams"
                      placeholder='请输入唯一性配置，例如: {"scope": "BATCH"}'
                      type="textarea"
                      :rows="2"
                    />
                    <NText depth="3" class="text-12px">
                      示例: {"scope": "BATCH", "message": "值重复"}
                    </NText>
                  </NSpace>
                </NFormItem>
              </NGridItem>
              <NGridItem>
                <NFormItem label="错误策略">
                  <NSelect v-model:value="rule.errorStrategy" :options="errorStrategyOptions" />
                </NFormItem>
              </NGridItem>
              <NGridItem>
                <NFormItem label="错误信息">
                  <NInput v-model:value="rule.errorMessage" placeholder="请输入自定义错误信息（可选）" />
                </NFormItem>
              </NGridItem>
            </NGrid>
          </NCard>
        </NSpace>
      </NForm>
      <template #footer>
        <NSpace justify="end">
          <NButton @click="closeDrawer">{{ $t('common.cancel') }}</NButton>
          <NButton type="primary" :loading="submitLoading" @click="handleSubmit">
            {{ $t('common.confirm') }}
          </NButton>
        </NSpace>
      </template>
    </NDrawerContent>
  </NDrawer>
</template>

<style scoped></style>
